<template>
  <div class="app-container">
    <el-form
      :model="queryParams"
      ref="queryRef"
      :inline="true"
      v-show="showSearch"
      label-width="68px"
    >
      <el-form-item label="视频标题" prop="title">
        <el-input
          v-model="queryParams.title"
          placeholder="请输入视频标题"
          clearable
          @keyup.enter="handleQuery"
        />
      </el-form-item>
      <el-form-item label="关联培训" prop="trainingId" style="width: 240px;">
        <el-select v-model="queryParams.trainingId" placeholder="请选择关联培训">
          <el-option
              v-for="item in trainingOptions"
              :label="item.label"
              :value="item.value"
            />
        </el-select>
      </el-form-item>
      <el-form-item label="上传时间" prop="uploadedAt">
        <el-date-picker
          clearable
          v-model="queryParams.uploadedAt"
          type="date"
          value-format="YYYY-MM-DD"
          placeholder="请选择上传时间"
        >
        </el-date-picker>
      </el-form-item>
      <el-form-item label="更新时间" prop="updatedAt">
        <el-date-picker
          clearable
          v-model="queryParams.updatedAt"
          type="date"
          value-format="YYYY-MM-DD"
          placeholder="请选择更新时间"
        >
        </el-date-picker>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" icon="Search" @click="handleQuery"
          >搜索</el-button
        >
        <el-button icon="Refresh" @click="resetQuery">重置</el-button>
      </el-form-item>
    </el-form>

    <el-row :gutter="10" class="mb8">
      <el-col :span="1.5">
        <el-button
          type="primary"
          plain
          icon="Plus"
          @click="handleAdd"
          v-hasPermi="['system:video:add']"
          >新增</el-button
        >
      </el-col>
      <el-col :span="1.5">
        <el-button
          type="success"
          plain
          icon="Edit"
          :disabled="single"
          @click="handleUpdate"
          v-hasPermi="['system:video:edit']"
          >修改</el-button
        >
      </el-col>
      <el-col :span="1.5">
        <el-button
          type="danger"
          plain
          icon="Delete"
          :disabled="multiple"
          @click="handleDelete"
          :limit="1"
          v-hasPermi="['system:video:remove']"
          >删除</el-button
        >
      </el-col>
      <el-col :span="1.5">
        <el-button
          type="warning"
          plain
          icon="Download"
          @click="handleExport"
          v-hasPermi="['system:video:export']"
          >导出</el-button
        >
      </el-col>
      <right-toolbar
        v-model:showSearch="showSearch"
        @queryTable="getList"
      ></right-toolbar>
    </el-row>

    <el-table
      v-loading="loading"
      :data="videoList"
      @selection-change="handleSelectionChange"
    >
      <el-table-column type="selection" width="55" align="center" />
      <el-table-column label="视频ID" align="center" prop="videoId" />
      <el-table-column label="视频标题" align="center" prop="title" />
      <el-table-column label="关联培训ID" align="center" prop="trainingId" />
      <el-table-column label="视频文件" align="center">
        <template #default="scope">
          <el-button
            link
            type="primary"
            @click="handlePreview(scope.row)"
            :disabled="!scope.row.videoUrl"
          >
            {{ scope.row.videoUrl ? "点击预览" : "无视频" }}
          </el-button>
        </template>
      </el-table-column>
      <el-table-column label="视频时长" align="center" prop="duration" />
      <el-table-column
        label="上传时间"
        align="center"
        prop="uploadedAt"
        width="180"
      >
        <template #default="scope">
          <span>{{
            parseTime(scope.row.uploadedAt, "{y}-{m}-{d} {h}:{i}:{s}")
          }}</span>
        </template>
      </el-table-column>
      <el-table-column
        label="更新时间"
        align="center"
        prop="updatedAt"
        width="180"
      >
        <template #default="scope">
          <span>{{
            parseTime(scope.row.updatedAt, "{y}-{m}-{d} {h}:{i}:{s}")
          }}</span>
        </template>
      </el-table-column>
      <el-table-column
        label="操作"
        align="center"
        class-name="small-padding fixed-width"
      >
        <template #default="scope">
          <el-button
            link
            type="primary"
            icon="Upload"
            @click="handleUpload(scope.row)"
            v-hasPermi="['system:video:edit']"
            >上传</el-button
          >
          <el-button
            link
            type="primary"
            icon="Edit"
            @click="handleUpdate(scope.row)"
            v-hasPermi="['system:video:edit']"
            >修改</el-button
          >
          <el-button
            link
            type="primary"
            icon="Delete"
            @click="handleDelete(scope.row)"
            v-hasPermi="['system:video:remove']"
            >删除</el-button
          >
        </template>
      </el-table-column>
    </el-table>

    <pagination
      v-show="total > 0"
      :total="total"
      v-model:page="queryParams.pageNum"
      v-model:limit="queryParams.pageSize"
      @pagination="getList"
    />

    <!-- 添加或修改视频对话框 -->
    <el-dialog :title="title" v-model="open" width="500px" append-to-body>
      <el-form ref="videoRef" :model="form" :rules="rules" label-width="80px">
        <el-form-item label="视频标题" prop="title">
          <el-input v-model="form.title" placeholder="请输入视频标题" />
        </el-form-item>
        <el-form-item label="关联培训" prop="trainingId">
          <el-select v-model="form.trainingId" placeholder="请选择关联培训">
          <el-option
              v-for="item in trainingOptions"
              :label="item.label"
              :value="item.value"
            />
        </el-select>
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary" @click="submitForm">确 定</el-button>
          <el-button @click="cancel">取 消</el-button>
        </div>
      </template>
    </el-dialog>
    <el-dialog
      title="上传视频"
      v-model="openUpload"
      width="500px"
      append-to-body
    >
      <el-form ref="videoRef" :model="form" label-width="80px">
        <el-form-item label="视频url" prop="title">
          <el-input disabled v-model="form.videoUrl" />
        </el-form-item>
        <el-form-item label="视频时长" prop="trainingId">
          <el-input disabled v-model="form.duration" />
        </el-form-item>
        <el-form-item label="视频预览" v-if="form.videoUrl">
          <video
            controls
            :src="form.videoUrl"
            style="width: 100%; max-height: 400px; border-radius: 4px"
            @loadedmetadata="handleVideoLoaded"
          >
            您的浏览器不支持视频播放
          </video>
          <div class="preview-tip" style="color: #666; margin-top: 8px">
            {{ videoPreviewStatus || "视频加载中..." }}
          </div>
        </el-form-item>
        <!-- 上传表单部分 -->
        <el-form-item>
          <el-upload
            ref="uploadRef"
            accept="video/*"
            action="#"
            :auto-upload="false"
            :on-change="handleFileSelect"
            :show-file-list="false"
          >
            <template #trigger>
              <el-button type="primary">选择视频</el-button>
            </template>
            <el-button
              type="success"
              @click="startChunkUpload"
              :disabled="!chunkState.selectedFile || chunkState.uploading"
            >
              {{
                chunkState.uploading
                  ? `上传中 (${chunkState.progress}%)`
                  : "开始上传"
              }}
            </el-button>
          </el-upload>

          <!-- 进度条 -->
          <el-progress
            v-if="chunkState.uploading"
            :percentage="chunkState.progress"
            :status="uploadStatus"
            style="margin-top: 10px"
          />
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary" @click="submitFileForm">确 定</el-button>
          <el-button @click="cancel">取 消</el-button>
        </div>
      </template>
    </el-dialog>
    <!-- 添加视频预览对话框 -->
    <el-dialog
      title="视频预览"
      v-model="openPreview"
      width="60%"
      append-to-body
      @close="handleVideoClose"
    >
      <video
        controls
        :src="previewVideoUrl"
        style="width: 100%; max-height: 70vh; border-radius: 4px"
        @loadedmetadata="handlePreviewLoaded"
        ref="preVideoRef"
      >
        您的浏览器不支持视频播放
      </video>
      <div
        class="preview-tip"
        style="color: #666; margin-top: 8px; text-align: center"
      >
        {{ videoPreviewStatus || "视频加载中..." }}
      </div>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary" @click="handleVideoClose">关 闭</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>

<script setup name="Video">
import SparkMD5 from "spark-md5";
import { ref } from "vue";
import {
  listVideo,
  getVideo,
  delVideo,
  addVideo,
  updateVideo,
  getUploadedChunks,
  uploadChunk,
  mergeChunks,
} from "@/api/system/video";
import { computed } from "vue";

const { proxy } = getCurrentInstance();

const videoList = ref([]);
const open = ref(false);
const loading = ref(true);
const showSearch = ref(true);
const ids = ref([]);
const single = ref(true);
const multiple = ref(true);
const total = ref(0);
const title = ref("");
const preVideoRef = ref(null);
const data = reactive({
  form: {},
  queryParams: {
    pageNum: 1,
    pageSize: 10,
    title: null,
    trainingId: null,
    videoUrl: null,
    duration: null,
    uploadedAt: null,
    updatedAt: null,
  },
  rules: {
    title: [{ required: true, message: "视频标题不能为空", trigger: "blur" }],
    trainingId: [
      { required: true, message: "关联培训ID不能为空", trigger: "blur" },
    ],
    videoUrl: [
      { required: true, message: "视频文件URL不能为空", trigger: "blur" },
    ],
  },
});

const { queryParams, form, rules } = toRefs(data);

/** 查询视频列表 */
function getList() {
  loading.value = true;
  listVideo(queryParams.value).then((response) => {
    videoList.value = response.rows;
    total.value = response.total;
    loading.value = false;
  });
}

// 取消按钮
function cancel() {
  open.value = false;
  openUpload.value = false;
  reset();
}

// 表单重置
function reset() {
  form.value = {
    videoId: null,
    title: null,
    trainingId: null,
    videoUrl: null,
    duration: null,
    uploadedAt: null,
    updatedAt: null,
  };
  proxy.resetForm("videoRef");
}

/** 搜索按钮操作 */
function handleQuery() {
  queryParams.value.pageNum = 1;
  getList();
}

/** 重置按钮操作 */
function resetQuery() {
  proxy.resetForm("queryRef");
  handleQuery();
}

// 多选框选中数据
function handleSelectionChange(selection) {
  ids.value = selection.map((item) => item.videoId);
  single.value = selection.length != 1;
  multiple.value = !selection.length;
}

/** 新增按钮操作 */
function handleAdd() {
  reset();
  open.value = true;
  title.value = "添加视频";
}

/** 修改按钮操作 */
function handleUpdate(row) {
  reset();
  const _videoId = row.videoId || ids.value;
  getVideo(_videoId).then((response) => {
    form.value = response.data;
    open.value = true;
    title.value = "修改视频";
  });
}

/** 提交按钮 */
function submitForm() {
  proxy.$refs["videoRef"].validate((valid) => {
    if (valid) {
      if (form.value.videoId != null) {
        updateVideo(form.value).then((response) => {
          proxy.$modal.msgSuccess("修改成功");
          open.value = false;
          getList();
        });
      } else {
        addVideo(form.value).then((response) => {
          proxy.$modal.msgSuccess("新增成功");
          open.value = false;
          getList();
        });
      }
    }
  });
}

/** 删除按钮操作 */
function handleDelete(row) {
  const _videoIds = row.videoId || ids.value;
  proxy.$modal
    .confirm('是否确认删除视频编号为"' + _videoIds + '"的数据项？')
    .then(function () {
      return delVideo(_videoIds);
    })
    .then(() => {
      getList();
      proxy.$modal.msgSuccess("删除成功");
    })
    .catch(() => {});
}

/** 导出按钮操作 */
function handleExport() {
  proxy.download(
    "system/video/export",
    {
      ...queryParams.value,
    },
    `video_${new Date().getTime()}.xlsx`
  );
}

getList();

const uploadRef = ref();

// 选择视频后获取视频时长
const handlebeforeUpload = (uploadFile, uploadFiles) => {
  const file = uploadFile.raw;

  if (file && file.type.startsWith("video")) {
    const videoElement = document.createElement("video");

    videoElement.onloadedmetadata = () => {
      form.value.duration = Math.floor(videoElement.duration);
    };

    videoElement.src = URL.createObjectURL(file);
  }
};

const openUpload = ref(false);

function handleUpload(row) {
  reset();
  openUpload.value = true;
  form.value.videoId = row.videoId;
  form.value.videoUrl = row.videoUrl;
  form.value.duration = row.duration;
  form.value.trainingId = row.trainingId;
}

function submitFileForm() {
  updateVideo(form.value).then((res) => {
    openUpload.value = false;
    getList();
  });
}

// 添加视频元数据加载处理
const handleVideoLoaded = (e) => {
  const video = e.target;
  videoPreviewStatus.value = `分辨率: ${video.videoWidth}x${video.videoHeight} 时长: ${form.value.duration}秒`;
};

// 添加预览相关变量
const openPreview = ref(false);
const previewVideoUrl = ref("");
const videoPreviewStatus = ref("");

// 添加预览处理方法
function handlePreview(row) {
  if (!row.videoUrl) {
    proxy.$modal.msgWarning("该视频尚未上传");
    return;
  }
  previewVideoUrl.value = row.videoUrl;
  openPreview.value = true;
  videoPreviewStatus.value = "";
}

// 添加视频元数据加载处理
const handlePreviewLoaded = (e) => {
  const video = e.target;
  videoPreviewStatus.value = `分辨率: ${video.videoWidth}x${
    video.videoHeight
  } 时长: ${Math.floor(video.duration)}秒`;
};

// 新增分片相关状态
const CHUNK_SIZE = 5 * 1024 * 1024; // 5MB
const chunkState = reactive({
  selectedFile: null,
  fileMD5: "",
  uploading: false,
  progress: 0,
  totalChunks: 0,
  uploadedChunks: new Set(),
});

// 修改文件选择处理（保留时长获取）
const handleFileSelect = async (uploadFile) => {
  const file = uploadFile.raw;

  // 确保表单数据已初始化
  if (!form.value.trainingId || !form.value.videoId) {
    proxy.$modal.msgError("请先选择关联的培训ID和视频ID");
    return;
  }

  // 保留原有的时长获取逻辑
  const videoElement = document.createElement("video");
  videoElement.onloadedmetadata = () => {
    form.value.duration = Math.floor(videoElement.duration);
  };
  videoElement.src = URL.createObjectURL(file);

  try {
    // 初始化分片状态
    chunkState.selectedFile = file;
    chunkState.fileMD5 = await calculateFileMD5(file);
    chunkState.totalChunks = Math.ceil(file.size / CHUNK_SIZE);

    // 使用新的API方法获取已上传分片
    const res = await getUploadedChunks({
      trainingId: form.value.trainingId,
      videoId: form.value.videoId,
      fileMd5: chunkState.fileMD5,
    });

    // 添加调试日志
    console.log("接口响应数据:", res);

    // 直接访问顶层 uploadedChunks 字段
    const uploaded = res.uploadedChunks || [];

    chunkState.uploadedChunks = new Set(uploaded);
    chunkState.progress = Math.round(
      (chunkState.uploadedChunks.size / chunkState.totalChunks) * 100
    );
  } catch (err) {
    proxy.$modal.msgError("初始化失败: " + err.message);
  }
};

// 分片上传方法（替换原有handleUploadAction）
const startChunkUpload = async () => {
  try {
    chunkState.uploading = true;

    for (let i = 0; i < chunkState.totalChunks; i++) {
      if (chunkState.uploadedChunks.has(i)) continue;

      const chunk = chunkState.selectedFile.slice(
        i * CHUNK_SIZE,
        (i + 1) * CHUNK_SIZE
      );

      const formData = new FormData();
      formData.append("file", chunk);
      formData.append("chunkIndex", i);
      formData.append("fileMd5", chunkState.fileMD5);

      // 使用新的分片上传接口
      await uploadChunk(form.value.trainingId, form.value.videoId, formData);

      chunkState.uploadedChunks.add(i);
      chunkState.progress = Math.round(
        ((i + 1) / chunkState.totalChunks) * 100
      );
    }

    const { url } = await mergeChunks(
      form.value.trainingId,
      form.value.videoId,
      {
        fileMd5: chunkState.fileMD5,
        fileName: chunkState.selectedFile.name,
        totalChunks: chunkState.totalChunks,
      }
    );
    console.log("完整合并响应:", url);
    form.value.videoUrl = url;
    proxy.$modal.msgSuccess("视频上传成功");
  } catch (err) {
    proxy.$modal.msgError("上传失败: " + err.message);
  } finally {
    chunkState.uploading = false;
  }
};

// 计算文件MD5（新增方法）
const calculateFileMD5 = (file) => {
  return new Promise((resolve) => {
    const spark = new SparkMD5.ArrayBuffer();
    const reader = new FileReader();

    reader.onload = (e) => {
      spark.append(e.target.result);
      resolve(spark.end());
    };
    reader.readAsArrayBuffer(file);
  });
};

const uploadStatus = computed(() => {
  if (chunkState.progress < 100) {
    return "warning";
  } else {
    return "success";
  }
});

const handleVideoClose = () => {
  preVideoRef.value.pause();
  openPreview.value = false;
};

import {
  listTraining,
} from "@/api/system/training";

const trainingOptions = ref([])
function initTrainingOptions() {
  listTraining().then((res) => {
    const {rows} = res
    trainingOptions.value = rows.map((row) => ({
      label: row.title,
      value: row.trainingId,
    }));

  })
}

initTrainingOptions()
</script>

<style scoped>
.uploader-example {
  width: 880px;
  padding: 15px;
  margin: 40px auto 0;
  font-size: 12px;
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.4);
}
.uploader-example .uploader-btn {
  margin-right: 4px;
}
.uploader-example .uploader-list {
  max-height: 440px;
  overflow: auto;
  overflow-x: hidden;
  overflow-y: auto;
}

.preview-tip {
  font-size: 12px;
  text-align: center;
}
</style>
